#include <iostream>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
#include<string>
#include <stdlib.h>
#include<stdio.h>
#include<string.h>
#include <errno.h>
#include<sys/stat.h>
#include<fcntl.h>

using namespace std;

int main()
{
    const char* msg0="hello print";
    const char* msg1="hello fwrite\n";
    const char* msg2="hello write\n";

    cout<<msg0<<endl;
    fwrite(msg1,strlen(msg1),1,stdout);
    write(1,msg2,strlen(msg2));
    return 0;
}
//动静态库这里也需要重新复习
// int main()
// {
//     int fd=open("myfile.txt",O_RDWR | O_CREAT);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     //先要把1关掉才能重定向到1
//     close(1);
//     dup2(fd,1);
//     for(;;)
//     {
//         char buffer[1024]={0};
//         //从标准输入里面去读，
//         ssize_t s=read(0,buffer,sizeof(buffer)-1);
//         if(s < 0)
//         {
//             perror("open");
//             break;
//         }
//         cout<<buffer;
//         fflush(stdout);
//     }
//     return 0;
// }
// int main()
// {
//     int fd=open("myfile.txt",O_RDWR | O_CREAT);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     close(1);
//     dup2(fd,1);
//     while(true)
//     {
//         char buffer[1024]={0};
//         ssize_t s=read(0,buffer,sizeof(buffer)-1);
//         if(s < 0)
//         {
//             perror("read:");
//             exit(-1);
//         }
//         cout<<buffer;
//         fflush(stdout);
//     }
//     close(fd);
//     return 0;
// }
// int main()
// {
//     //dup2可以重定向一个新的文件描述符
//     //int dup2(int oldfd,int newfd);
//     int fd=open("myfile.txt",O_CREAT | O_RDWR);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     close(1);
//     //将文件描述符重定向到标准输出
//     dup2(fd,1);
//     for(;;)
//     {
//         char buffer[1024]={0};
//         //首先得从标准输入里面读取数据到buffer里面去，然后才能输出到buffer
//         ssize_t s=read(0,buffer,sizeof(buffer)-1);
//         if(s < 0)
//         {
//             perror("read");
//             break;
//         }
//         cout<<buffer<<endl;
//         fflush(stdout);
//     }
//     return 0;
// }
// int main()
// {
//     close(1);
//     int fd=open("myfile.txt",O_WRONLY | O_CREAT,0644);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     cout<<"fd:"<<fd<<endl;
//     //我们关闭了标准输出，原本应该输出到显示器上的东西，却
//     //输出道理文件当中
//     //这就叫做重定向
//     fflush(stdout);
//     close(fd);
//     return 0;
// }
// int main()
// {
//     close(2);
//     //close(0);
//     int fd=open("myfile.txt",O_RDONLY);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     cout<<"fd:"<<fd<<endl;
//     //分配的规则就是找到第一个没有被使用的文件描述符

//     close(fd);
//     return 0;
// }
// int main()
// {
//     int fd=open("myfile.txt",O_RDONLY);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     cout<<"fd:"<<fd<<endl;
//     const char* msg="hello lyy\n";
//     write(1,msg,strlen(msg));
//     close(fd); 
//     return 0;
// }
// int main()
// {
//     int fd=open("myfile.txt",O_RDONLY);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     char buffer[1024];
//     while(true)
//     {
//         ssize_t s=read(fd,buffer,sizeof(buffer));
//         if(s > 0)
//         {
//             buffer[s]=0;
//             cout<<buffer;
//         }
//         else
//         {
//             break;
//         }
//     }    
//     close(fd);
//     return 0;
// }

// int main()
// {
//     umask(0);
//     int fd=open("myfile.txt",O_WRONLY);
//     if(fd < 0)
//     {
//         perror("open()");
//         exit(-1);
//     }
//     int count=5;
//     const char* msg="I am so cool\n";
//     while(count--)
//     {
//         write(fd,msg,strlen(msg));
//     }
//     close(fd);
//     return 0;
// }

// int main()
// {
//     int fd=open("myfile.txt",O_RDONLY);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     const char* msg="hello ";
//     char buffer[1024];
//     while(true)
//     {
//         ssize_t s=read(fd,buffer,strlen(msg));
//         if(s > 0)
//         {
//             buffer[s]=0;
//             cout<<buffer;
//         }
//         else
//         {
//             break;
//         }
//     }
//     close(fd);
//     return 0;
// }
// int main()
// {
//     int fd=open("myfile.txt",O_RDONLY | O_CREAT);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     const char* msg="hello yangyi\n";
//     char buffer[1024];
//     while(true)
//     {
//         //由于read函数无法判断
//         ssize_t s=read(fd,buffer,strlen(msg));
//         if(s > 0)
//         {
//             buffer[s]=0;
//             cout<<buffer;
//         }
//         else
//         {
//             break;
//         }
//     }
//     close(fd);
//     return 0;
// }
// int main()
// {
//     umask(0);
//     int fd=open("myfile.txt",O_WRONLY | O_CREAT,0664);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     const char* buffer="hello yangyi\n";
//     int count=5;
//     while(count--)
//     {
//         write(fd,buffer,strlen(buffer));
//     }
//     close(fd);
// }
// int main()
// {
//     //给予进程创建文件的最大权限，避免后面的不确定性
//     umask(0);
//     int fd=open("myfile.txt",O_WRONLY | O_CREAT,0664);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     int count=5;
//     while(count--)
//     const char* msg="hello yangyi\n";
//     int len=strlen(msg);

//     while(count--)
//     {
//         write(fd,msg,len);
//     }
//     close(fd);
//     return 0;
// }
// int main()
// {
//     umask(0);
//     int fd=open("myfile",O_WRONLY | O_CREAT,0664);
//     if(fd < 0)
//     {
//         perror("open");
//         exit(-1);
//     }
//     int count=5;
//     const char* msg="hello yangyi\n";
//     int len=strlen(msg);
//     while(count--)
//     {
//         //根据文件描述符找到缓冲区的首地址
//         write(fd,msg,len);
//     }
//     //最后记得关闭文件描述符
//     close(fd);
//     return 0;
// }
// int main()
// {
//     //设置权限描述符
//     umask(0);
//     //设置文件打开时的权限
//     int fd=open("myfile.txt",O_WRONLY|O_CREAT,0664);
//     if(fd < 0)
//     {
//         perror("open");
//         return 1;
//     }
//     int count=5;
//     const char* msg="hello yangyi\n";
//     int len=strlen(msg);
//     while(count--)
//     {
//         //msg是缓冲区的首地址，len代表着这次希望读入多少数据
//         //返回值是这一次一共读取了多少字节的数据
//         write(fd,msg,len);
//     }
//     close(fd);
//     return 0;
// }
// int main()
// {
//     const char* msg="hello NUC\n";
//     fwrite(msg,strlen(msg),1,stdout);
//     printf("hello printf\n");
//     cout<<"hello cout"<<endl;
//     fprintf(stdout,"hello fprintf\n");
//     return 0;
// }
// int main()
// {
//     const char* msg="hello lyy\n";
//     //直接将内容输出到显示屏
//     fwrite(msg,strlen(msg),1,stdout);

//     printf("hello world\n");
//     fprintf(stdout,"hello printf\n");
//     return 0;
// }
// int main()
// {
//     FILE* fp=fopen("myfile.txt","w");
//     if(fp==nullptr)
//     {
//         perror("fopen()");
//         exit(-1);
//     }
//     const char* msg="hello Liuyangyi\n";
//     int count=5;
//     while(count--)
//     {
//         fwrite(msg,strlen(msg),1,fp);
//     }
//     fclose(fp);
//     return 0;
// }
// int main()
// {
//     FILE* fp=fopen("myfile.txt","r");
//     if(fp==nullptr)
//     {
//         perror("fopen");
//         exit(-1);
//     }
//     char buffer[1024];
//     const char* msg="hello yangyi";
//     while(true)
//     {
//         //一次只读一个字节的数据，读13条数据
//         ssize_t s=fread(buffer,1,strlen(msg),fp);
//         if(s > 0)
//         {
//             buffer[s]=0;
//             cout<<buffer;
//         }
//         if(feof(fp))
//         {
//             break;
//         }
//     }
//     fclose(fp);
//     return 0;
// }
// int main()
// {
//     FILE* fp=fopen("myfile.txt","w");
//     if(fp==nullptr)
//     {
//         perror("fopen()");
//         exit(-1);
//     }
//     const char* msg="hello NUC";
//     int count=5;
//     while(count--)
//     {
//         fwrite(msg,1,strlen(msg),fp);
//     }
//     fclose(fp);
//     return 0;
// }
// int main()
// {
//     char arr[5]={1,2,3,4,5};
//     int ret=strlen(arr);
//     cout<<ret<<endl;
//     return 0;
// }int main()
// {
//     FILE* fp=fopen("myfile.txt","r");
//     if(fp==nullptr)
//     {
//         perror("fopen");
//         exit(-1);
//     }
//     char buffer[1024];
//     const char* msg="hello yangyi\n";
//     cout<<strlen(msg)<<endl;
//     while(true)
//     {
//         ssize_t s=fread(buffer,1,strlen(msg),fp);
//         if(s > 0)
//         {
//             //其实之前的数据它读到了但是读到了空
//             buffer[s]=0;
//             cout<<buffer[1]<<endl;
//         }
//         if(feof(fp))
//         {
//             break;
//         }
//     }
//     fclose(fp);

//     return 0;
// }
// 
// int main()
// {
//     FILE* fp=fopen("myfile.txt","r");
//     if(fp==nullptr)
//     {
//         perror("fopen");
//         exit(-1);
//     }
//     char buffer[1024];
//     const char* msg="hello yangyi\n";
//     while(true)
//     {
//         //这里代表一次读取多少字节，一共读取多少次
//         //这里的数据一个字符只有一个字节
//         //这个函数无法判断文件结束或者终止
//         ssize_t s=fread(buffer,1,strlen(msg),fp);
//         if(s > 0)
//         {
//             buffer[s]=0;
//             cout<<buffer<<endl;
//         }
//         if(feof(fp))
//         {
//             break;
//         }
//     }
//     fclose(fp);
//     return 0;
// }
// int main()
// {
//     const char* arr="helloyangyi";
//     int ret=strlen(arr);
//     int size=sizeof(arr);
//     cout<<"ret:"<<ret<<endl;
//     cout<<"size:"<<size<<endl;
//     return 0;
// }
// int main()
// {
//     FILE* fp=fopen("myfile.txt","r");
//     if(!fp)
//     {
//         perror("fopen");
//         exit(-1);
//     }
//     char buffer[1024];
//     const char* msg="hello yangyi\n";
//     while(true)
//     {
//         ssize_t s=fread(buffer,)
//     }
//     return 0;
// }
// int main()
// {
//     FILE* fp=fopen("myfile.txt","w");
//     if(fp==nullptr)
//     {
//         perror("fopen()");
//         exit(-1);
//     }
//     const char* msg="hello shanxi\n";
//     int count=10;
//     while(count--)
//     {
//         fwrite(msg,strlen(msg),1,fp);
//     }
//     fclose(fp);
//     return 0;
// }
// int main()
// {
//     FILE* fp=fopen("myfile.txt","w");
//     if(fp==nullptr)
//     {
//         perror("fopen()");
//         exit(-1);
//     }
//     const char* msg="hello yangyi\n";
//     int count=5;
//     while(count--)
//     {
//         fwrite(msg,strlen(msg),1,fp);
//     }
//     fclose(fp);
//     return 0;
// }
// int main()
// {
//     //以写的方式打开
//     //以这样的方式就能够向文件当中写入内容
//     FILE* fp=fopen("myfile.txt","w");
//     if(!fp)
//     {
//         perror("fopen()");
//         exit(-1);
//     }
//     const char* msg="hello NUC\n";
//     int count=5;
//     while(count--)
//     {
//         //这里的数据代表读出多少条记录
//         fwrite(msg,strlen(msg),1,fp);
//     }
//     fclose(fp);
//     return 0;
// }
//目前由两个问题============简易的shell和环境变量
//制作建议的xshell====================================
//还有动静态库======================================
//这里简易的zshell还是需要继续打磨的
/*
用fork创建子进程后执行的是和父进程相同的程序，但是可能是不同的
代码分支，当进程调用程序替换接口的时候，该进程的用户空间代码和
数据完全被新程序替换，从新程序的启动处开始执行，调用并不创建
新进程。所以调用前后进程的id并未改变
int execl(const char* path,const char* arg)
类似的函数只有失败的返回值，没有成功的返回值
============================函数解释
这些函数如果调用成功，则加载新的程序从启动代码开始执行，不再返回
*/
// int main()
// {
//     char* const argv[]={"ps","ajx",nullptr};
//     const char* envp[]={"/home/lyy/105/lesson_02.24",nullptr};

//     // execl("/bin/ps","ps","ajx",nullptr);
//     // execlp("ps","ajx",nullptr);
//     execv("/bin/ps",argv);
//     return 0;
// }
// int main()
// {
//     //经典代码建议反复练习
//     //这里由对应的操作
//     char* const argv[]={"ps","-ajx",nullptr};
//     char* const envp[]={"PATH=/bin:/usr/bin","TERM=console",nullptr};

//     //execl("bin/ps","ps","-ajx",nullptr);
//     //之后的代码就不会再执行
//     //execlp("ps","-ajx",nullptr,envp);
//     //execv("bin/ps",argv);
//     //这里需要自己维护环境变量
//     execve("/bin/ps",argv,envp);
//     return 0;
// }
// int main()
// {
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id == 0)
//     {
//         cout<<"child is running ["<<getpid()<<"]"<<endl;
//         sleep(10);
//         exit(-2);
//     }
//     else
//     {
//         int status=0;
//         pid_t ret=0;
//         do
//         {
//             if(ret == 0)
//             {
//                 cout<<"child is running"<<endl;
//             }
//             ret=waitpid(-1,&status,WNOHANG);
//             sleep(1);
//         } while (ret == 0);
        
//         if(ret == id && WIFEXITED(status))
//         {
//             cout<<"wait child success,child return code is:"<<WEXITSTATUS(status)<<endl;
//         }
//         else
//         {
//             cout<<"wait failed"<<endl;
//             return 1;
//         }
//     }
//     return 0;
// }
// int main()
// {
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id == 0)
//     {
//         cout<<"child is run,pid is:"<<getpid()<<endl;
//         sleep(3);
//         exit(-2);
//     }
//     else 
//     {
//         int status=0;
//         pid_t ret=0;
//         do
//         {
//             ret=waitpid(-1,&status,WNOHANG);
//             //这里为0说明子进程并没有退出
//             if(ret == 0)
//             {
//                 cout<<"child is running"<<endl;
//             }
//             sleep(1);
//         } while (ret == 0);

//         if(WIFEXITED(status) && ret==id)
//         {
//             cout<<"wait child 3s success,child return code is:"<<WEXITSTATUS(status)<<endl;
//         }
//         else
//         {
//             cout<<"wait child failed"<<endl;
//             return 1;
//         }
//     }
//     return 0;
// }
// int main()
// {
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id == 0)
//     {
//         cout<<"child is running [ "<<getpid()<<" ] "<<endl;
//         sleep(1);
//         exit(-2);
//     }
//     else
//     {
//         int status=0;
//         pid_t ret=waitpid(-1,&status,0);
//         if(ret == id && WIFEXITED(status))
//         {
//             //退出码的状态获取到
//             cout<<"wait child 5 s success,child code is: "<<WEXITSTATUS(status)<<endl;
//             sleep(1);
//         }
//         else
//         {
//             cout<<"wait failed"<<endl;
//             return 1;
//         }
//     }
//     return 0;
// }

// int main()
// {
//     pid_t id = fork();
//     if (id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if (id == 0)
//     {
//         cout << "child is run,id is:" << getpid() << endl;
//         sleep(5);
//         exit(-2);
//     }
//     else
//     {
//         int status = 0;
//         pid_t ret = waitpid(-1, &status, 0); // 阻塞式等待
//         cout << "this is test for wait" << endl;
//         if (WEXITED(status) && ret == id)
//         {
//             cout << "wait child 5s success,child return code is:" << WEXITSTATUS(status) << endl;
//         }
//         else
//         {
//             cout << "wait child failed,return:" << endl;
//             return 1;
//         }
//     }
//     return 0;
// }

// int main()
// {
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id == 0)
//     {
//         cout<<"I am a child"<<endl;
//         sleep(1);
//         exit(-2);
//     }
//     else 
//     {
//         int status=0;
//         pid_t ret=waitpid(-1,&status,0);
//         //返回以后的退出码就是254
//         if(ret == id && WIFEXITED(status))
//         {
//             cout<<"wait success,wait code:"<<WEXITSTATUS(status)<<endl;
//         }
//         else
//         {
//             cout<<"failed"<<endl;
//             //如果子进程回收失败就直接退出程序
//             return -1;
//         }
//     }
//     return 0;
// }
// int main()
// {
//     pid_t pid=fork();
//     if (pid < 0)
//     {
//         perror("fork()");
//         return 1;
//     }
//     else if (pid == 0)
//     { // child
//         printf("child is run, pid is : %d\n", getpid());
//         sleep(5);
//         exit(257);
//     }
//     else
//     {
//         int status = 0;
//         pid_t ret = waitpid(-1, &status, 0); // 阻塞式等待，等待5S
//         printf("this is test for wait\n");
//         if (WIFEXITED(status) && ret == pid)
//         {
//             printf("wait child 5s success, child return code is :%d.\n", WEXITSTATUS(status));
//         }
//         else
//         {
//             printf("wait child failed, return.\n");
//             return 1;
//         }
//     }
//     return 0;
// }

// int main()
// {
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id ==0)
//     {
//         cout<<"I am a child"<<endl;
//         sleep(1);
//     }
//     else
//     {
//         int status=0;
//         int ret=wait(&status);
//         //根据这样的情况就可以判断子进程的退出状态了
//         if(ret > 0 && (status & 0x7F)==0)
//         {
//             cout<<"child exit code:"<<(status >> 8)&0xFF
//             <<endl;
//         }
//         else if(ret < 0)
//         {
//             cout<<"signal code:"<<(status >> 8)&0x7F<<endl;
//         }
//     }
//     return 0;
// }
// int main()
// {
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     else if(id == 0)
//     {
//         sleep(2);
//         exit(10);
//     }
//     else
//     {
//         int status=0;
//         //因为这里关心进程的退出状态所以要设置一个状态位
//         //如果不关心的话可以设置为nullptr
//         //拓展：
//         //status是一个位图前一共有十六位前八位代表着退出状态
//         //后八位代表着是否正常退出WIFEXITED判断
//         //前八位由WEXITSTATUS来获取
//         int ret=wait(&status);
//         //这里的子进程正常退出
//         if(ret > 0 && (status & 0x7F) == 0)
//         {
//             cout<<"child exit code:"<<((status >> 8)& 0xFF)<<endl;
//         }
//         //这里子进程异常退出
//         else if(ret < 0)
//         {
//             cout<<"sig code:"<<(status & 0x7F)<<endl;
//         }
//     }
//     return 0;
// }
/*
fork()函数是一个非常重要的函数，他从已知进程当中创建出一个
新的函数，为子进程，原进程为父进程，子进程返回0，父进程返回子进程
的id，当调用fork之后，内核做了什么呢？
1.分配新的物理内存块和内核数据结构给子进程
2.将父进程部分的数据结构内容拷贝至子进程
3.添加子进程到系统进程列表中
4.fork之后开始使用调度器
*/
// int main()
// {
//     //输出父进程id
//     cout<<"before fork():"<<getpid()<<endl;
//     pid_t id=fork();
//     if(id < 0)
//     {
//         perror("fork()");
//         exit(-1);
//     }
//     //显然这里的代码被执行了两遍
//     cout<<"after fork()"<<getpid()<<"fork return "<<id<<endl;
//     //为什么会产生这样的现象
//     //fork之前父进程独立运行，fork之后呢？
//     //父子两个进程执行流分别执行，调度器来决定

//     //写时拷贝
//     //通常情况下父子代码共享，数据也是共享的，当双方对数据
//     //都不做修改的时候，共享，但是一旦有其中一方想要写数据
//     //就会发生写时拷贝，单独拷贝一份数据到自己的地址空间内
//     return 0;
// }
/*
fork常规的用法，一个父进程希望复制自己，是父子进程执行不同的
代码段，例如父进程等待客户端的请求，生成子进程去处理客户端的
请求
进程的退出场景：
代码运行完毕，正常退出
代码运行完毕，但是结果不正确
代码异常终止

退出方法：
从主线程返回
调用exit函数
调用_exit()接口

异常终止：
ctr+C
*/
// int main()
// {
//     printf("hello\n");
//     //_exit()函数不会刷新缓冲流，关闭流等，不会执行用户定义的
//     //清理函数
//     _exit(10);
//     return 0;
// }
/*
子进程一旦变成僵尸进程即便是9号信号也无能为力，因为谁也没有办法
杀死一个已经死去的进程，但是子进程的退出状态，完成任务情况
我们是需要知道的，这个时候就需要用到进程等待的接口来对子进程
的资源进行回收

=========================================================
1.wait方法
pid_t wait(int* status);
//这里的参数时输出型参数，可以获取子进程的退出状态，如果对
子进程的退出状态并不关心的话，我们也可以设置为nullptr
2.waitpid方法
pid_t waitpid(pid_t pid,int* status,int options)
返回值：
当正常返回的时候，会收到子进程的pid
如果设置了选项WNOHANG，而调用中waitpid发现没有已退出的子进程
可以收集，则返回0，如果调用失败的话，返回相应的错误码
参数：
Pid=-1：等待任意一个子进程，与wait等效
pid>0:设置pid等待相应的进程
status:
//这里返回一个真值，用来判断子进程是否正常退出，用于知道后面的
WEXITSTATUS 的状态码的返回
WIFEXITED(status):若是正常终止子进程返回的状态，则为真，查看
进程是否正常退出
WEXITSTATUS(status):若是WIFEXITED非零，提取子进程退出码(查看进程
的退出码)
*/